package com.koron.standard.gradeStock.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.koron.standard.bean.base.BaseBean;
import com.koron.standard.bean.query.PageQuery;
import com.koron.standard.gradeStock.bean.dto.GradeDTO;
import com.koron.standard.gradeStock.bean.excel.GradeExcel;
import com.koron.standard.gradeStock.bean.po.Grade;
import com.koron.standard.gradeStock.bean.po.GradeItem;
import com.koron.standard.gradeStock.bean.query.GradeQuery;
import com.koron.standard.gradeStock.bean.vo.GradeVO;
import com.koron.standard.gradeStock.mapper.GradeMapper;
import com.koron.standard.utils.CommonUtils;
import com.koron.standard.utils.StandardCodeTools;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 大修分级分项验收标准(Grade)表服务实现类
 *
 * @author jzp
 * @since 2021-09-26
 */
@Service
public class GradeService extends ServiceImpl<GradeMapper, Grade> {

    @Autowired
    private GradeItemService gradeItemService;

    public QueryWrapper<GradeVO> queryWrapper(GradeQuery query) {
        query.setAppids(CommonUtils.getDefaultAppids(query.getAppids()));
        query.setPublicStatus(CommonUtils.getDefaultPublicStatus(query.getPublicStatus()));

        QueryWrapper<GradeVO> wrapper = new QueryWrapper<>();
        wrapper.like(StrUtil.isNotEmpty(query.getCode()), "c_grade.code", query.getCode());
        wrapper.like(StrUtil.isNotEmpty(query.getName()), "c_grade.name", query.getName());
        wrapper.eq(StrUtil.isNotEmpty(query.getTypeId()), "c_grade.type_id", query.getTypeId());
        wrapper.like(StrUtil.isNotEmpty(query.getTypeName()), "c_type.name", query.getTypeName());

        if (query.getPublicStatus() != null && query.getPublicStatus() > 0) {
            // 如果是共有的
            wrapper.and(w -> w.eq("c_grade.public_status", query.getPublicStatus())
                    .or(CollUtil.isNotEmpty(query.getAppids()))
                    .in(CollUtil.isNotEmpty(query.getAppids()), "c_grade.appid", query.getAppids()));
        } else {
            wrapper.in(CollUtil.isNotEmpty(query.getAppids()), "c_grade.appid", query.getAppids());
        }

        wrapper.eq(query.getStatus()!=null, "c_grade.status", query.getStatus());
        wrapper.eq(StrUtil.isNotEmpty(query.getDeptId()), "c_grade.dept_id", query.getDeptId());
        wrapper.like(StrUtil.isNotEmpty(query.getDeptName()), "c_grade.dept_name", query.getDeptName());
        if (CollUtil.isNotEmpty(query.getDates())) {
            wrapper.between("c_grade.create_time", query.getDates().get(0), query.getDates().get(1));
        }
        wrapper.eq("c_grade.delete_flag", 0);
        return wrapper;
    }

    public List<GradeDTO> list(GradeQuery query) {
        QueryWrapper<GradeVO> wrapper = queryWrapper(query);
        List<GradeVO> list = getBaseMapper().selectPageVo(wrapper);
        if (CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<GradeItem> gradeItems = gradeItemService.listByGradeIds(list.stream().map(BaseBean::getId).collect(Collectors.toList()));
        // <sourceId : gradeItem>
        Map<String, List<GradeItem>> collect = gradeItems.stream().collect(Collectors.groupingBy(GradeItem::getGradeId));
        return list.stream().map(gradeVO -> {
            GradeDTO gradeDTO = BeanUtil.toBean(gradeVO, GradeDTO.class);
            gradeDTO.setItems(collect.get(gradeVO.getId()));
            return gradeDTO;
        }).collect(Collectors.toList());
    }

    public List<GradeExcel> listExcel(GradeQuery query) {
        QueryWrapper<GradeVO> wrapper = queryWrapper(query);
        List<GradeVO> list = getBaseMapper().selectPageVo(wrapper);
        if (CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<GradeItem> gradeItems = gradeItemService.listByGradeIds(list.stream().map(BaseBean::getId).collect(Collectors.toList()));
        // <sourceId : gradeItem>
        Map<String, List<GradeItem>> collect = gradeItems.stream().collect(Collectors.groupingBy(GradeItem::getGradeId));

        return list.stream().flatMap(gradeVO -> Optional.ofNullable(collect.get(gradeVO.getId()))
                .map(gradeItemsNa -> gradeItemsNa.stream().map(gradeItem -> {
                    GradeExcel gradeExcel = BeanUtil.toBean(gradeVO, GradeExcel.class);
                    gradeExcel.setGradeName(gradeItem.getName());
                    gradeExcel.setLevel(gradeItem.getLevel());
                    gradeExcel.setMajor(gradeItem.getMajor());
                    gradeExcel.setContext(gradeItem.getContext());
                    gradeExcel.setContextStandard(gradeItem.getContextStandard());
                    return gradeExcel;
                })).orElse(Stream.of(BeanUtil.toBean(gradeVO, GradeExcel.class)))).collect(Collectors.toList());
    }

    public Page<GradeVO> page(PageQuery<GradeVO> pageQuery, GradeQuery query) {
        QueryWrapper<GradeVO> wrapper = queryWrapper(query);
        Page<GradeVO> page = pageQuery.convertPage();
        List<OrderItem> orders = pageQuery.getOrders();
        for (OrderItem order : orders) {
            if (order.getColumn().equals("type_name")) {
                order.setColumn("c_type.name");
            } else if (order.getColumn().equals("app_name")) {
                order.setColumn("s_app.name");
            } else {
                order.setColumn("c_grade." + order.getColumn());
            }
        }
        getBaseMapper().selectPageVo(page, wrapper);
        return page;
    }

    public GradeDTO getDtoById(String id) {
        GradeVO gradeVO = getBaseMapper().getVoById(id);
        GradeDTO gradeDTO = new GradeDTO();
        BeanUtils.copyProperties(gradeVO, gradeDTO);
        List<GradeItem> gradeItems = gradeItemService.listByGradeId(id);
        gradeDTO.setItems(gradeItems);
        return gradeDTO;
    }

    public void saveDto(GradeDTO gradeDTO) {
        // 设置编码
        gradeDTO.setCode(StandardCodeTools.getGradeCode());

        // 默认草稿
        gradeDTO.setStatus(0);

        // 保存
        updateDtoById(gradeDTO);

    }

    @Transactional(rollbackFor = RuntimeException.class)
    public void updateDtoById(GradeDTO gradeDTO) {
        // 1. 删除所有子项-大修分级分项验收标准下作业项目
        gradeItemService.removeByGradeId(gradeDTO.getId());

        // 2. 保存或更新基本信息
        saveOrUpdate(gradeDTO);

        // 3. 保存子项信息
        List<GradeItem> gradeItems = Optional.ofNullable(gradeDTO.getItems()).orElse(new ArrayList<>());
        for (GradeItem gradeItem : gradeItems) {
            gradeItem.setGradeId(gradeDTO.getId());
        }
        gradeItemService.saveBatch(gradeItems);

    }

    public void updateToPublic(List<String> ids) {
        List<Grade> grades = new ArrayList<>();
        for (String id : ids) {
            Grade grade = new Grade();
            grade.setId(id);
            grade.setPublicStatus(1);
            grades.add(grade);
        }
        updateBatchById(grades);
    }

    public void updateStatus(String id, Integer status) {
        LambdaUpdateWrapper<Grade> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Grade::getId, id);
        wrapper.set(Grade::getStatus, status);
        update(wrapper);
    }

}
